home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / news / readers / skim-0.8 / skim-0 / skim-0.8.4 / SkimUtils.c < prev    next >
C/C++ Source or Header  |  1996-02-18  |  9KB  |  446 lines

  1. /*
  2.  * NAME
  3.  *   SkimUtils.c
  4.  * DESCRIPTION
  5.  *   Miscellaneous skim related utility functions.
  6.  * COPYRIGHT
  7.  *   Skim - Off-line news reading package optimized for slow lines.
  8.  *   Copyright (C) 1996  Rene W.J. Pijlman
  9.  *
  10.  *   This program is free software; you can redistribute it and/or modify
  11.  *   it under the terms of the GNU General Public License as published by
  12.  *   the Free Software Foundation; either version 2 of the License, or
  13.  *   (at your option) any later version.
  14.  *
  15.  *   This program is distributed in the hope that it will be useful,
  16.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *   GNU General Public License for more details.
  19.  *
  20.  *   You should have received a copy of the GNU General Public License
  21.  *   along with this program; if not, write to the Free Software
  22.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  * VERSION
  24.  *   Skim version 0.8.4.
  25.  */
  26.  
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include <sys/wait.h>
  31. #include <unistd.h>
  32. #include <pwd.h>
  33. #include <sys/types.h>
  34.  
  35.  
  36. #include "Skim.h"
  37. #include "SkimUtils.h"
  38. #include "StandardIO.h"
  39.  
  40. FILE_ID("$Header: /home/rene/sys/CVS_MasterSourceRepository/skim/SkimUtils.c,v 1.7 1996/02/17 19:38:52 rene Exp $");
  41.  
  42. char * SkimDirectory( void )
  43. {
  44.     char * SkimDirectory;
  45.  
  46.     if ( ( SkimDirectory = getenv( "SKIMDIR" ) ) == NULL )
  47.     {
  48.         SIOPrintf( StandardError, 
  49.                            "Environment variable SKIMDIR is not set.\n" );
  50.         exit( EXIT_FAILURE );
  51.     }
  52.  
  53.     return SkimDirectory;
  54. }
  55.  
  56.  
  57. Boolean AppendFieldFromSeparatorRecord(
  58.     VarBuf Target,
  59.     VarBuf Overview,
  60.     char Separator,
  61.     unsigned int InputOffset,
  62.     void (Convert)(VarBuf) )
  63. {
  64.     VarBuf Scratch = VBCreate();
  65.     Boolean Success = True;
  66.  
  67.     char * p = VBAsString( Overview );
  68.     int i;
  69.  
  70.     for ( i = 0; Success && i < InputOffset; i++ )
  71.     {
  72.         p = strchr( p, Separator );
  73.  
  74.         if ( p != NULL )
  75.         {
  76.             p++;
  77.         }
  78.         else
  79.         {
  80.             Success = False;
  81.         }
  82.     }
  83.  
  84.     if ( Success )
  85.     {
  86.     for ( ; *p != '\0' && *p != Separator; p++ )
  87.     {
  88.         VBAppendCharacter( Scratch, *p );
  89.     }
  90.  
  91.     if ( Convert != NULL )
  92.     {
  93.         Convert( Scratch );
  94.     }
  95.  
  96.     VBAppendVB( Target, Scratch );
  97.     }
  98.  
  99.     VBDestroy( Scratch );
  100.  
  101.     return Success;
  102. }
  103.  
  104.  
  105. Boolean AppendFieldFromFixedRecord(
  106.     VarBuf Target,
  107.     VarBuf Record,
  108.     unsigned int Offset,
  109.     int Length,
  110.     void (Convert)(VarBuf) )
  111. {
  112.     VarBuf Scratch = VBCreate();
  113.     Boolean Success = True;
  114.     char * From;
  115.  
  116.     assert( Length == VARIABLE_LENGTH || Length >= 0 );
  117.  
  118.     if ( ( Length == VARIABLE_LENGTH && VBSize( Record ) < Offset ) ||
  119.          ( VBSize( Record) < Offset + Length ) )
  120.     {
  121.         Success = False;
  122.     }
  123.     else
  124.     {
  125.     From = VBAsString(Record) + Offset;
  126.  
  127.     if ( Length == VARIABLE_LENGTH )
  128.     {
  129.         VBAppendString( Scratch, From );
  130.     }
  131.     else
  132.     {
  133.         unsigned int i;
  134.  
  135.         for ( i = 0; i < Length; i ++ )
  136.         {
  137.         VBAppendCharacter( Scratch, *(From + i) );
  138.         }
  139.     }
  140.  
  141.     if ( Convert != NULL )
  142.     {
  143.         Convert( Scratch );
  144.     }
  145.  
  146.     VBAppendVB( Target, Scratch );
  147.     }
  148.  
  149.     VBDestroy( Scratch );
  150.  
  151.     return Success;
  152. }
  153.  
  154.  
  155. void WaitForAChild( const char * ProgramName )
  156. {
  157.     int Status;
  158.  
  159.     if ( wait( &Status ) <= 0 )
  160.     {
  161.     SIOPrintError( "wait" );
  162.     exit( EXIT_FAILURE );
  163.     }
  164.  
  165.     if ( !WIFEXITED( Status ) )
  166.     {
  167.     SIOPrintf( StandardError,
  168.                        "Warning: '%s' process terminated with an error.\n", 
  169.                ProgramName );
  170.     }
  171. }
  172.  
  173.  
  174. int OffsetOfSelection( void )
  175. {
  176.     return 0;
  177. }
  178.  
  179. int OffsetOfArticleNumber( void )
  180. {
  181.     return OffsetOfSelection() + LengthSelection + 1;
  182. }
  183.  
  184. int OffsetOfAuthor( void )
  185. {
  186.     return OffsetOfArticleNumber() + LengthArticleNumber + 1;
  187. }
  188.  
  189. int LengthOfAuthor( void )
  190. {
  191.     static int Length = 0;
  192.  
  193.     if ( Length == 0 )
  194.     {
  195.     char * p = getenv( "SKIMLENGTHAUTHOR" );
  196.  
  197.     if ( p != NULL )
  198.     {
  199.         Length = atoi( p );
  200.         if ( Length < 1 )
  201.         {
  202.         SIOPrintf( StandardError,
  203.             "invalid value in environment variable SKIMLENGTHAUTHOR: %s", p );
  204.         exit( EXIT_FAILURE );
  205.         }
  206.     }
  207.     else
  208.     {
  209.         Length = DefaultLengthOfAuthor;
  210.     }
  211.     }
  212.  
  213.     return Length;
  214. }
  215.  
  216.  
  217. int LengthOfNumberOfLines( void )
  218. {
  219.     static int Length = 0;
  220.  
  221.     if ( Length == 0 )
  222.     {
  223.     char * p = getenv( "SKIMLENGTHLINES" );
  224.  
  225.     if ( p != NULL )
  226.     {
  227.         Length = atoi( p );
  228.         if ( Length < 1 )
  229.         {
  230.         SIOPrintf( StandardError,
  231.     "invalid value in environment variable SKIMLENGTHNUMBEROFLINES: %s", p );
  232.         exit( EXIT_FAILURE );
  233.         }
  234.     }
  235.     else
  236.     {
  237.         Length = DefaultLengthOfNumberOfLines;
  238.     }
  239.     }
  240.  
  241.     return Length;
  242. }
  243.  
  244.  
  245. int OffsetOfLines( void )
  246. {
  247.     return OffsetOfAuthor() + LengthOfAuthor() + 1;
  248. }
  249.  
  250. int OffsetOfSubject( void )
  251. {
  252.     return OffsetOfLines() + LengthOfNumberOfLines() + 1;
  253. }
  254.  
  255.  
  256. /*
  257.  * `Target' contains the `From:' header field of a USENET article. Parse the
  258.  * field, and extract the real name of the author.
  259.  *
  260.  * The formats which are recognized are the formats allowed by RFC-1036:
  261.  *
  262.  *     1) email@subdomain.domain (Real Name)
  263.  *     2) Real Name <email@subdomain.domain>
  264.  *     3) email@subdomain.domain
  265.  *
  266.  * In pattern 2, double quote characters (") are removed, since some posters
  267.  * appear to use formats like:
  268.  *
  269.  *     4) "Real Name" <email@subdomain.domain>
  270.  *
  271.  * When there is no real name (as in pattern 3) or when the `From:' header
  272.  * field is not is one of the allowed formats, no conversion is applied
  273.  * (except for pattern 5 below).
  274.  *
  275.  * A trailing string "()" is removed from the resulting Author field, since
  276.  * some posters use formats like:
  277.  *
  278.  *     5) email@subdomain.domain ()
  279.  */
  280. void AuthorFromFromField( VarBuf Target )
  281. {
  282.     VarBuf From = VBCreate();
  283.     char * LeftBracket;
  284.     char * RightBracket;
  285.     char * FromAsString;
  286.     char * p;
  287.  
  288.     VBAppendVB( From, Target );
  289.     VBReset( Target );
  290.  
  291.     FromAsString = VBAsString(From);
  292.  
  293.     /* Pattern 1. */
  294.     if ( ( LeftBracket = strchr( FromAsString, '(' ) ) != NULL &&
  295.          ( RightBracket = strchr( FromAsString, ')' ) ) != NULL &&
  296.          LeftBracket > FromAsString &&
  297.          RightBracket > LeftBracket )
  298.     {
  299.         for ( p = LeftBracket + 1; p < RightBracket; p++ )
  300.         {
  301.             VBAppendCharacter( Target, *p );
  302.         }
  303.     }
  304.     /* Pattern 2. */
  305.     else if ( ( LeftBracket = strchr( FromAsString, '<' ) ) != NULL &&
  306.               ( RightBracket = strchr( FromAsString, '>' ) ) != NULL &&
  307.               LeftBracket > FromAsString &&
  308.               RightBracket > LeftBracket )
  309.     {
  310.         for ( p = FromAsString; p < LeftBracket; p++ )
  311.         {
  312.             if ( *p != '"' )
  313.             {
  314.         VBAppendCharacter( Target, *p );
  315.             }
  316.         }
  317.     }
  318.  
  319.     VBRemoveLeadingBlanks( Target );
  320.     VBRemoveTrailingBlanks( Target );
  321.  
  322.     /*
  323.      * This also catches the case where () is empty or blank in pattern 1, or 
  324.      * only blanks preceed <> in pattern 2.
  325.      */
  326.     if ( VBSize( Target ) == 0 )
  327.     {
  328.         VBAppendVB( Target, From );
  329.  
  330.     VBRemoveLeadingBlanks( Target );
  331.     VBRemoveTrailingBlanks( Target );
  332.     }
  333.  
  334.     if ( VBSize(Target) > 2 &&
  335.          VBAsString(Target)[ VBSize(Target) - 2 ] == '(' &&
  336.          VBAsString(Target)[ VBSize(Target) - 1 ] == ')' )
  337.     {
  338.         VBTruncate( Target, VBSize(Target) - 2 );
  339.  
  340.     VBRemoveLeadingBlanks( Target );
  341.         VBRemoveTrailingBlanks( Target );
  342.     }
  343.  
  344.     VBDestroy( From );
  345. }
  346.  
  347.  
  348. char * HomeDirectory( void )
  349. {
  350.     char * HomeDir;
  351.  
  352.     HomeDir= getenv("HOME");
  353.     if ( HomeDir== NULL )
  354.     {
  355.     struct passwd * passwd_entry = getpwuid( getuid() );
  356.     if ( passwd_entry != NULL )
  357.     {
  358.         assert( passwd_entry->pw_dir != NULL );
  359.  
  360.         HomeDir= passwd_entry->pw_dir;
  361.     }
  362.     else
  363.     { 
  364.         SIOPrintError("getpwuid");
  365.         exit( EXIT_FAILURE );
  366.     }
  367.     }
  368.  
  369.     return HomeDir;
  370. }
  371.  
  372.  
  373. VarBuf GetSignature( void )
  374. {
  375.     VarBuf New = NULL;
  376.     VarBuf SignatureFileName = VBCreate();
  377.     StandardIO SignatureFile = SIOCreate();
  378.  
  379.     VBPrintf( SignatureFileName, "%s/.signature", HomeDirectory() );
  380.  
  381.     SIOFileOpen( SignatureFile, VBAsString(SignatureFileName),
  382.                  OpenModeReadIgnore );
  383.  
  384.     if ( SIOIsOpenForRead(SignatureFile) )
  385.     {
  386.     New = VBCreate();
  387.  
  388.     VBReadFile( New, SignatureFile );
  389.     }
  390.  
  391.     VBDestroy(SignatureFileName);
  392.     SIODestroy(SignatureFile);
  393.  
  394.     return New;
  395. }
  396.  
  397. void ItemsFromEnvironment(
  398.     VarBuf * Signature,
  399.     VarBuf * X_NewsReader,
  400.     VarBuf * From,
  401.     VarBuf * ReplyTo,
  402.     VarBuf * Path,
  403.     VarBuf * Organization )
  404. {
  405.     char * p;
  406.  
  407.     assert( Signature != NULL && *Signature == NULL );
  408.     assert( X_NewsReader != NULL && *X_NewsReader == NULL );
  409.     assert( From != NULL && *From == NULL );
  410.     assert( ReplyTo != NULL && *ReplyTo == NULL );
  411.     assert( Path != NULL && *Path == NULL );
  412.     assert( Organization != NULL && *Organization == NULL );
  413.  
  414.     *Signature = GetSignature();
  415.  
  416.     p = getenv("SKIMFROM");
  417.     if ( p != NULL )
  418.     {
  419.     *From = VBCreate();
  420.     VBAppendString( *From, p );
  421.     }
  422.  
  423.     p = getenv("SKIMPATH");
  424.     if ( p != NULL )
  425.     {
  426.     *Path = VBCreate();
  427.     VBAppendString( *Path, p );
  428.     }
  429.  
  430.     p = getenv("SKIMREPLYTO");
  431.     if ( p != NULL )
  432.     {
  433.     *ReplyTo = VBCreate();
  434.     VBAppendString( *ReplyTo, p );
  435.     }
  436.  
  437.     p = getenv("SKIMORGANIZATION");
  438.     if ( p != NULL )
  439.     {
  440.     *Organization = VBCreate();
  441.     VBAppendString( *Organization, p );
  442.     }
  443.  
  444.     *X_NewsReader = VBCreateString("skim 0.8.4" );
  445. }
  446.